﻿using sqlsearcher.Models;
using sqlsearcher.Models.Services;
using sqlsearcher.Services.DB;
using sqlsearcher.Services.IService;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace sqlsearcher.Services
{
    public class SearchManager
    {
        public static ISearch dbSearch = null;
        public static ISqlDbUtils dbUtils = null;
        public static ISqlHelper sqlhelper = null;
        public static string Server = string.Empty;
        public static int LoginDBType = 0;
        public ISqlHelper InitDB(string server, string uid, string pwd,int dbType)
        {
            switch (dbType)
            {
                case (int)AppEnum.DBType.SQLServer:
                     sqlhelper = new SqlServerHelper(server, uid, pwd, dbType);
                    dbUtils = new SqlServerDbUtils();
                    Server = server;
                    dbSearch = new SqlServerSearch();
                    LoginDBType = (int)AppEnum.DBType.SQLServer;
                    break;
                case (int)AppEnum.DBType.MySQL:
                    sqlhelper=new MySQLHelper(server, uid, pwd, dbType);
                    dbUtils = new MySqlDbUtils();
                    Server = server;
                    dbSearch = new MySqlSearch();
                    LoginDBType = (int)AppEnum.DBType.MySQL;
                    break;
                default:
                    break;
            }
            return sqlhelper;
        }

        /// <summary>
        /// 登录
        /// </summary>
        public Tuple<bool, string> Login(string server, string uid, string pwd, int _dbType)
        {
            var isConn = false;
            if (string.IsNullOrEmpty(server) || string.IsNullOrEmpty(uid) || string.IsNullOrEmpty(pwd))
            {
                return Tuple.Create(false, "登录失败，登录凭证不正确");
            }
            try
            {

                InitDB(server, uid, pwd, _dbType);
                isConn = sqlhelper.TryConn();
                if (isConn)
                {
                    TFac<JsonManager>.Instance.LogHistory(server, uid, pwd, _dbType);
                }
            }
            catch (Exception ex) { }
            return Tuple.Create(isConn, isConn ? "登录成功" : "登录失败");
        }

        public Tuple<bool, List<TreeMapInfo>> GetDataBases()
        {
            return dbSearch.GetDataBases(dbUtils);
        }

        public Tuple<bool, List<TreeMapInfo>> GetTables(string db)
        {
            return dbSearch.GetTables(dbUtils,db);
        }

        

        public DataTable GetDs(string sql, string db)
        {
            return dbSearch.GetDs(dbUtils,sql, db);
        }

        public DataSet GetDataSets(string sql, string db)
        {
            return dbSearch.GetDataSets(dbUtils, sql, db);
        }

        public ArrayList getIndexArray(String inputStr, String findStr)
        {
            ArrayList list = new ArrayList();
            int start = 0;
            while (start < inputStr.Length)
            {
                int index = inputStr.IndexOf(findStr, start);
                if (index >= 0)
                {
                    list.Add(index);
                    start = index + findStr.Length;
                }
                else
                {
                    break;
                }
            }
            return list;

        }

        

        public string Create(string template, string tbName, string dbName)
        {
            var details =dbSearch. GetCodeDetails(dbUtils,dbName,tbName);
            if (details.Item1 == 0) { return "未找到相关信息!"; }
            var list = details.Item2.ToList<FiledInfo>();
            #region + 替换多行
            var matchs = PrintHelper.GetMatchString(template, "$listBegin", "$listEnd");

            foreach (var item in matchs)
            {
                if (string.IsNullOrEmpty(item.Trim())) continue;
                var mm = "";
                foreach (FiledInfo f in list)
                {
                    var sourceTmp = item;
                    sourceTmp = sourceTmp.Format(new { columnDataType = ConvertType(f.cType,LoginDBType), columnName = f.cName, columnDesc = f.cDesc });

                    mm += sourceTmp;
                }

                template = template.Replace(item, mm);
            }
            #endregion

            #region + 替换表
            template = template.Format(new { className = tbName });
            template = template.Format(new { classDesc = dbSearch.GetTableDesc(dbUtils,tbName, dbName) });
            #endregion

            #region + 移除替换标记
            template = template.Format(new { listBegin = "", listEnd = "" });
            #endregion

            return template;
        }

        private string ConvertType(string p,int dbType)
        {
            var typeDic = new Dictionary<string, string>();

            if (dbType == (int)AppEnum.DBType.SQLServer)
            {
                typeDic["int"] = "int?";
                typeDic["text"] = "string";
                typeDic["bigint"] = "Int64";
                typeDic["binary"] = "Byte[]";
                typeDic["bit"] = "bool?";
                typeDic["char"] = "string";
                typeDic["datetime"] = "DateTime?";
                typeDic["decimal"] = "decimal?";
                typeDic["float"] = "double?";
                typeDic["image"] = "Byte[]";
                typeDic["money"] = "decimal?";
                typeDic["nchar"] = "string";
                typeDic["ntext"] = "string";
                typeDic["numeric"] = "decimal?";
                typeDic["nvarchar"] = "string";
                typeDic["real"] = "Single";
                typeDic["smalldatetime"] = "DateTime?";
                typeDic["smallint"] = "Int16?";
                typeDic["smallmoney"] = "decimal?";
                typeDic["timestamp"] = "DateTime?";
                typeDic["tinyint"] = "Byte";
                typeDic["uniqueidentifier"] = "Guid";
                typeDic["varbinary"] = "Byte[]";
                typeDic["varchar"] = "string";
                typeDic["Variant"] = "Object";
                if (typeDic.ContainsKey(p))
                    return typeDic[p];
            }
            else if (dbType == (int)AppEnum.DBType.MySQL)
            {
                typeDic["int"] = "Integer";
                typeDic["tinyint"] = "Integer";
                typeDic["smallint"] = "Integer";
                typeDic["mediumint"] = "Integer";

                typeDic["varchar"] = "String";
                typeDic["char"] = "String";
                typeDic["tinytext"] = "String";
                typeDic["mediumtext"] = "String";
                typeDic["text"] = "String";
                typeDic["longtext"] = "String";

                typeDic["bigint"] = "Long";
                typeDic["float"] = "Float";
                typeDic["bit(1)"] = "Boolean";
                typeDic["double"] = "Double";
                typeDic["decimal"] = "Java.math.BigDecimal";
                typeDic["datetime"] = "LocalDateTime";
                typeDic["time"] = "String";
                typeDic["date"] = "LocalDateTime";
                foreach (var item in typeDic.Keys)
                {
                    if (p.ToLower().IndexOf(item) != -1)
                    {
                        return typeDic[item];
                    }
                }
            }
            
            return p;
        }


        public int AddDescription(string server,string sql)
        {
            int res = 0;
            try
            {
                res = dbUtils.ExecSPSql(server,sql);
            }
            catch
            {
                res = 0;
            }
            return res;
        }


        

        
   
        public DataTable GetDataTableBySql(string db,string sql)
        {
            return dbUtils.Query(db,sql);
        }

        public Tuple<bool, List<TreeMapInfo>> GetColumns( string db, string value)
        {
            return dbSearch.GetColumns(dbUtils, db, value);
        }

        public Tuple<int, DataTable> GetDetails( string db, string value)
        {
            return dbSearch.GetDetails(dbUtils, db, value);
        }

        public Tuple<int, DataTable> GetDescs(string db, string tb)
        {
            return dbSearch.GetDescs(dbUtils, db, tb);
        }

        public DataTable GetTablesByDB( string db)
        {
            return dbSearch.GetTablesByDB(dbUtils, db);
        }

        public string GetTableDescSQL()
        {
            return dbSearch.GetTableDescSQL();
        }
    }
}
